/**
 * @author Tobias Boehm
 *
 * 06.06.2011
 */
package org.anddev.andengine.extension.tbsengine.match.gamestate;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.anddev.andengine.extension.tbsengine.faction.AbsBaseFaction;
import org.anddev.andengine.extension.tbsengine.match.AbsServerMatch;
import org.anddev.andengine.extension.tbsengine.match.AbsServerMatchPreparation;
import org.anddev.andengine.extension.tbsengine.match.AbsStep;
import org.anddev.andengine.extension.tbsengine.match.Round;
import org.anddev.andengine.extension.tbsengine.match.Turn;
import org.anddev.andengine.extension.tbsengine.team.Team;

/**
 * This is an abstract server side implementation
 * of {@link AbsGlobalGameState}. You should extend
 * this class in order to create a server side
 * representation of a global game state.
 *
 * @author Tobias Boehm
 *
 * @param <MatchClass> - An implementation of {@link AbsServerMatch}
 * @param <MatchPreparationClass> - An implementation of {@link AbsServerMatchPreparation}
 * @param <PlayerGameStateClass> - An implementation of {@link AbsPlayerGameState}.
 * @param <BaseFactionClass> - An implementation of {@link AbsBaseFaction}
 */
public abstract class AbsServerGlobalGameState<MatchClass extends AbsServerMatch<?,?,PlayerGameStateClass,?,?,?,MatchPreparationClass>,
											   MatchPreparationClass extends AbsServerMatchPreparation<?,MatchPreparationClass,?,?,?,?>,
											   PlayerGameStateClass extends AbsPlayerGameState<BaseFactionClass>,
											   BaseFactionClass extends AbsBaseFaction> 
									
											   extends AbsGlobalGameState<MatchClass,PlayerGameStateClass, BaseFactionClass> {

	/**
	 * This is the default constructor which
	 * creates a server global game state
	 * to a corresponding match.
	 * 
	 * @param pMatch - The corresponding match.
	 */
	public AbsServerGlobalGameState(MatchClass pMatch) {
		super(pMatch);
		
		this.initializeGlobalGameState();
	}

	/**
	 * This method should create a map of player IDs and
	 * corresponding player game states. You may find
	 * all necessary information in the parameter objects.
	 * 
	 * @param mTeams - All available teams.
	 * @param matchPreparation - The match preparation object
	 * @return
	 */
	protected abstract Map<UUID, PlayerGameStateClass> createServerPlayerIDGameStatesMap(
			Map<Integer, Team> pTeams, MatchPreparationClass pMatchPreparation);
	
	/**
	 * This method calls its match to announce
	 * the start of a new {@link Turn}.
	 */
	@Override
	public void onTurnStarted(Turn pCurrentTurn) {
		
		super.onTurnStarted(pCurrentTurn);
		
		this.mMatch.announceTurnStart(pCurrentTurn);
	}

	/**
	 * This method calls its match to announce
	 * the start of a new {@link Round}.
	 */
	@Override
	public void onRoundStarted(Round<PlayerGameStateClass> pRound) {
		
		this.mMatch.announceRoundStart(pRound);	
	}
	
	/**
	 * This method calls its match to announce
	 * that the current {@link Round} is complete.
	 */
	@Override
	public void onRoundCompleted(Round<PlayerGameStateClass> pRound) {
		super.onRoundCompleted(pRound);
		
		this.mMatch.announceRoundCompleted(pRound);
	}
	
	/**
	 * This method calls its match to announce
	 * that the current {@link Turn} is complete.
	 */
	@Override
	public void onTurnCompleted(Turn pTurn) {
				
		this.mMatch.announceTurnComplete(pTurn);
		
		super.onTurnCompleted(pTurn);
	}
	
	/**
	 * This method calls its match to announce
	 * that the current step is complete
	 */
	@Override
	public void onStepCompleted(AbsStep pStep) {
		super.onStepCompleted(pStep);
		
		this.mMatch.announceStepComplete(pStep);
	}

	@Override
	protected Map<UUID, PlayerGameStateClass> createPlayerIDsGameStatesMap() {
		
		return this.createServerPlayerIDGameStatesMap(this.mTeams, this.mMatch.getMatchPreparation());
		
	}

	@Override
	protected Map<Integer, Team> createTeams() {
		
		final HashMap<Integer,Team> teams = new HashMap<Integer, Team>();
		
		teams.putAll(this.mMatch.getMatchPreparation().getTeamIDsTeamsMap());
		
		return teams;
	}
}
